<?php

declare(strict_types=1);

namespace App\Master\Framework\Library\Tencent;


use App\Master\Framework\Extend\Module;
use App\Master\Framework\Library\Library;
use App\Utils\Common;
use App\Utils\Control\AuthSite;
use Illuminate\Support\Facades\Cache;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Faceid\V20180301\FaceidClient;
use TencentCloud\Faceid\V20180301\Models\IdCardVerificationRequest;

/**
 * 人脸核身 等
 */
class FaceLibrary extends Library
{
    protected string $base_uri = 'https://miniprogram-kyc.tencentcloudapi.com';
    protected array $config = [];

    /**
     * 实例化
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     */
    public function __construct()
    {
        // 腾讯云人脸开发配置
        $config = Module::_SetupModule("TencentConfig")['face'] ?? [];
        $this->config = [
            'SecretId'  => $config['secret_id'],
            'SecretKey'  => $config['secret_key'],
            'appId'     => $config['app_id'],
            'secret'    => $config['secret'],
        ];
    }

    /**
     * 身份证二要素
     * @param string $idCard 身份证
     * @param string $name 姓名
     * @return bool
     */
    public function IdCardVerification(string $idCard,string $name)
    {
        try {
            $cred = new Credential($this->config['SecretId'], $this->config['SecretKey']);
            $client = new FaceidClient($cred,'');
            $req = new IdCardVerificationRequest();
            $req->fromJsonString(json_encode([
                'IdCard' => $idCard,
                'Name' => $name,
            ]));
            $response = $client->IdCardVerification($req);
            $json = $response->toJsonString();
            $body = json_decode($json, true);
            if (!isset($body['Result']) || $body['Result'] != '0') {
                return $this->error(!empty($body['Description']) ? $body['Description'] : 'Error_0', $body);
            }

            return $this->success('校验通过', $body);
        } catch (TencentCloudSDKException $e){
            return $this->error($e->getMessage());
        }
    }

    public function getAccessToken()
    {
        $data = [
            'appId' => $this->config['appId'],
            'secret' => $this->config['secret'],
            'grant_type' => 'client_credential',
            'version' => '1.0.0',
        ];
        $response = $this->getJson("/api/oauth2/access_token", $data);
        if ($response->getStatusCode() != 200) {
            return $this->error($response->getReasonPhrase());
        }
        $json = $response->getBody()->getContents();
        $body = json_decode($json, true);
        if (!isset($body['code']) || $body['code'] != '0') {
            return $this->error(!empty($body['msg']) ? $body['msg'] : 'Error_0', $body);
        }

        return $this->success('获取成功', $body);
    }

    /**
     * 获取 SIGN ticket
     * @return bool
     */
    public function getTicket()
    {
        if (!$this->getAccessToken()) {
            return $this->error($this->getMessage(),$this->getData());
        }
        $access_token = $this->getData()['access_token'] ?? '';
        $data = [
            'appId' => $this->config['appId'],
            'access_token' => $access_token,
            'type' => 'SIGN',
            'version' => '1.0.0',
        ];
        $response = $this->getJson("/api/oauth2/api_ticket", $data);
        if ($response->getStatusCode() != 200) {
            return $this->error($response->getReasonPhrase());
        }

        $json = $response->getBody()->getContents();
        $body = json_decode($json, true);
        if (!isset($body['code']) || $body['code'] != '0') {
            return $this->error(!empty($body['msg']) ? $body['msg'] : 'Error_0', $body);
        }

        return $this->success('获取成功', $body);
    }

    /**
     * 获取 SIGN ticket
     * @return bool
     */
    public function getNonceTicket()
    {
        if (!$this->getAccessToken()) {
            return $this->error($this->getMessage(),$this->getData());
        }
        $access_token = $this->getData()['access_token'] ?? '';
        $data = [
            'appId' => $this->config['appId'],
            'access_token' => $access_token,
            'type' => 'NONCE',
            'version' => '1.0.0',
        ];
        $response = $this->getJson(uri:"/api/oauth2/api_ticket",params: $data);
        if ($response->getStatusCode() != 200) {
            return $this->error($response->getReasonPhrase());
        }

        $json = $response->getBody()->getContents();
        $body = json_decode($json, true);
        if (!isset($body['code']) || $body['code'] != '0') {
            return $this->error(!empty($body['msg']) ? $body['msg'] : 'Error_0', $body);
        }

        return $this->success('获取成功', $body);
    }

    /**
     * h5 识别认证
     * @param string $userId
     * @param string $orderNo
     * @param string $name
     * @param string $idNo
     * @param string $callback_uri
     * @return bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getFaceCheckH5JumpUri(string $userId,string $orderNo,string $name,string $idNo,string $callback_uri = '')
    {
        if (!$this->getTicket()) {
            return $this->error($this->getMessage(),$this->getData());
        }
        $ticket = $this->getData()['tickets'][0]['value'] ?? '';
        $nonce = Common::createNonceStr(32);
        //获取签名
        $sign_data = [
            'appId' => $this->config['appId'],
            'userId' => $userId,
            'nonce' => $nonce,
            'version' => '1.0.0',
            'ticket' => $ticket,
        ];
        asort($sign_data);//排序
        $sign_string = join('', $sign_data);
        $sign = sha1($sign_string);
        $data = [
            'appId' => $this->config['appId'],
            'orderNo' => $orderNo,
            'name' => $name,
            'idNo' => $idNo,
            'userId' => $userId,
            'version' => '1.0.0',
            'sign' => $sign,
            'nonce' => $nonce,
        ];
        $response = $this->postJson(uri:"/api/server/getAdvFaceId?orderNo={$orderNo}",params: $data,base_uri: 'https://kyc1.qcloud.com');
        if ($response->getStatusCode() != 200) {
            return $this->error($response->getReasonPhrase());
        }

        $json = $response->getBody()->getContents();
        $body = json_decode($json, true);
        if (!isset($body['code']) || $body['code'] != '0') {
            return $this->error(!empty($body['msg']) ? $body['msg'] : 'Error_0', $body ?? []);
        }
        // 生成h5签名
        $h5_sign = [
            'appId'   => $this->config['appId'],
            'orderNo' => $orderNo,
            'userId'  => $userId,
            'version' => '1.0.0',
            'faceId'  => $body['result']['faceId'],
            'ticket'  => $ticket,
            'nonce'   => $nonce,
        ];
        asort($h5_sign); //排序
        $sign_string = join('', $h5_sign);
        $sign        = sha1($sign_string);
        // 生成h5签名 end

        $params = [
            'appId'   => $this->config['appId'],
            'version' => '1.0.0',
            'nonce'   => $nonce,
            'orderNo' => $orderNo,
            'faceId'  => $body['result']['faceId'],
            'url' => $callback_uri,
            'userId'  => $userId,
            'sign'   => $sign,
            'from' => 'browser',
            'optimalDomain' => $body['result']['optimalDomain']
        ];
        return $this->success("获取成功", $params);
        return $this->success('获取成功',['url' => "https://{$body['result']['optimalDomain']}/api/web/login?" . http_build_query($params)]);
    }

    /**
     * 合作方后台上传身份信息
     * @param string $userId 外部用户id
     * @param string $orderNo 外部订单号
     * @param string $name 用户姓名
     * @param string $idNo 用户身份证号
     * @return bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getAdvFaceId(string $userId,string $orderNo,string $name,string $idNo)
    {
        if (!$this->getTicket()) {
            return $this->error($this->getMessage(),$this->getData());
        }
        $ticket = $this->getData()['tickets'][0]['value'] ?? '';
        $nonce = Common::createNonceStr(32);
        //获取签名
        $sign_data = [
            'appId' => $this->config['appId'],
            'userId' => $userId,
            'nonce' => $nonce,
            'version' => '1.0.0',
            'ticket' => $ticket,
        ];
        asort($sign_data);//排序
        $sign_string = join('', $sign_data);
        $sign = sha1($sign_string);
        $data = [
            'appId' => $this->config['appId'],
            'orderNo' => $orderNo,
            'name' => $name,
            'idNo' => $idNo,
            'userId' => $userId,
            'version' => '1.0.0',
            'sign' => $sign,
            'nonce' => $nonce,
        ];
        $response = $this->postJson(uri:"/api/server/getAdvFaceId?orderNo={$orderNo}",params: $data,base_uri: 'https://kyc1.qcloud.com');
        if ($response->getStatusCode() != 200) {
            return $this->error($response->getReasonPhrase());
        }

        $json = $response->getBody()->getContents();
        $body = json_decode($json, true);
        if (!isset($body['code']) || $body['code'] != '0') {
            return $this->error(!empty($body['msg']) ? $body['msg'] : 'Error_0', $body ?? []);
        }

        return $this->success('获取成功', $body);
    }

    /**
     * 人脸核身结果查询接口(升级)
     * @param string $orderNo 订单号，字母/数字组成的字符串,是您需要查询结果的人脸核身订单号
     * @param int $getFile 是否需要获取人脸识别的视频和文件，值为1则返回视频和照片、值为2则返回照片、值为3则返回视频；其他则不返回
     * @param string $queryVersion 查询接口版本号(传1.0则返回 sdk 版本号和 trtc 标识)
     * @return bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     * @Notice https://cloud.tencent.com/document/product/1007/61302
     */
    public function getFaceRecord(string $orderNo,int $getFile = 0,string $queryVersion = '')
    {
        if (!$this->getTicket()) {
            return $this->error($this->getMessage(),$this->getData());
        }
        $ticket = $this->getData()['tickets'][0]['value'] ?? '';
        $nonce = Common::createNonceStr(32);

        //获取签名
        $sign_data = [
            'appId' => $this->config['appId'],
            'orderNo'  => $orderNo,
            'version' => '1.0.0',
            'ticket'  => $ticket,
            'nonce'   => $nonce
        ];
        asort($sign_data);//排序
        $sign_string = join('', $sign_data);
        $sign = sha1($sign_string);
        $data = [
            'appId' => $this->config['appId'],
            'version' => '1.0.0',
            'nonce' => $nonce,
            'orderNo' => $orderNo,
            'sign' => $sign,
            'getFile' => $getFile,
            'queryVersion' => $queryVersion
        ];

        $response = $this->postJson("/api/v2/base/queryfacerecord?orderNo={$orderNo}",$data);
        if ($response->getStatusCode() != 200) {
            return $this->error($response->getReasonPhrase());
        }

        $json = $response->getBody()->getContents();
        $body = json_decode($json, true);
        if (!isset($body['code']) || $body['code'] != '0') {
            return $this->error(!empty($body['msg']) ? $body['msg'] : 'Error_0', $body ?? []);
        }

        return $this->success('获取成功', $body);
    }
}